#pragma once
#include <QString>
#include <QIcon>
#include <QUuid>
#include <QDateTime>
#include <QFileInfo>
#include <QBuffer>
#include <QRegularExpressionMatch>

#include "base.qpb.h"

namespace model {

///////////////////////////
/// 工具类函数
///////////////////////////

inline QString getFileName(const QString& path){
    return QFileInfo(path).fileName();
}

#define TAG QString("[%1:%2]").arg(model::getFileName(__FILE__),QString::number(__LINE__))
#define LOG() qDebug().noquote() << TAG

inline QString formatTime(int64_t timestamp){
    QDateTime date = QDateTime::fromSecsSinceEpoch(timestamp);
    return date.toString("yyyy/MM/dd hh:mm:ss");
}

inline int64_t getTime(){
    return QDateTime::currentSecsSinceEpoch();
}

// 数据转换成QIcon
inline QIcon makeIcon(const QByteArray& data){
    QPixmap p;
    p.loadFromData(data);
    return QIcon(p);
}

// 获取文件中的二进制内容
inline QByteArray loadFiletoByteArray(const QString& path){
    QByteArray data;
    QFile file(path);
    if(!file.open(QFile::ReadOnly)){
        LOG() << "文件打开失败";
    }else{
        data = file.readAll();
    }
    file.close();
    return data;
}

// 二进制内容写到某个文件里
inline void writeByteArrayToFile(const QByteArray& content, const QString& path){
    QFile file(path);
    if(!file.open(QFile::WriteOnly)){
        LOG() << "文件打开失败";
        return ;
    }
    file.write(content); // 直接写就行了
    file.flush();        // 刷新缓冲区
    file.close();
}

// 获得图片的二进制数据
inline QByteArray loadImageToByteArray(QString& path){
    QByteArray btyeArray;

    QImage image(path);
    if(image.isNull()) {
        LOG() << "图⽚⽆法加载!";
        return btyeArray;
    };

    // 支持多种类型
    QFileInfo fileInfo(path);
    QString type = fileInfo.suffix().toUpper();
    QStringList supportedTypes{"PNG", "JPG", "JPEG", "BMP", "GIF", "TIFF"};

    // 进行转换
    QBuffer buffer(&btyeArray);
    buffer.open(QIODevice::WriteOnly);
    if(supportedTypes.contains(type)){
        image.save(&buffer, type.toStdString().c_str());
    }else{
        LOG() << "图片类型⽆法加载!";
    }

    return btyeArray;
}

// 手机号格式验证
inline QString verifyPhone(const QString& phone)
{
    static QRegularExpression re("^1\\d{10}$");  // 以1开头，后跟10个数字，共11位
    QRegularExpressionMatch match = re.match(phone);
    if (match.hasMatch()) {
        return "";
    } else {
        return "手机号格式不正确";
    }
}

enum MessageType {
    TEXT_TYPE = 0,      // ⽂本消息
    IMAGE_TYPE,     // 图⽚消息
    FILE_TYPE,      // ⽂件消息
    SPEECH_TYPE,    // 语⾳消息
    UNKNOWN_TYPE    // 错误类型
};


///////////////////////////
/// 用户信息
///////////////////////////
class UserInfo{
public:
    QString m_userId = "";       // ID
    QString m_nickName = "";     // 昵称
    QString m_description = "";  // 个性签名
    QString m_phone = "";        // 手机号
    QIcon m_avatar;              // 头像

    void load(const im::UserInfo& userInfo){
        m_userId = userInfo.userId();
        m_nickName = userInfo.nickname();
        m_description = userInfo.description();
        m_phone = userInfo.phone();
        if(userInfo.avatar().isEmpty()){
            m_avatar = QIcon(":/resource/image/defaultAvatar.png"); // 默认头像
        }else{
            m_avatar = makeIcon(userInfo.avatar());
        }
    }
};


///////////////////////////
/// 消息体
///////////////////////////
class Message{
public:
    QString m_messageId = "";           // 消息id
    QString m_chatSessionId = "";       // 群id
    QString m_time = "";                // 发送时间 eg: 12/9 16:05
    UserInfo m_sender;                  // 发送者
    MessageType m_type = TEXT_TYPE;     // 消息类型
    QByteArray m_content;               // 消息内容
    QString m_fileName = "";            // 文件名
    QString m_fileId = "";              // 消息内容的id

    // 工厂模式，某人在某群发送了某种类型的消息，extraInfo只有为文件消息的时候使用
    static Message makeMessage(const UserInfo& sender, const QString& chatSessionId,
                               MessageType& type, const QByteArray& content, const QString& extraInfo){
        if(type == TEXT_TYPE){
            return makeTextMessage(sender, chatSessionId, content);
        }else if(type == IMAGE_TYPE){
            return makeImageMessage(sender, chatSessionId, content);
        }else if(type == SPEECH_TYPE){
            return makeSpeechMessage(sender, chatSessionId, content);
        }else if(type == FILE_TYPE){
            return makeFileMessage(sender, chatSessionId, content, extraInfo);
        }else{
            return Message();
        }
    }

    void load(const im::MessageInfo& msgInfo){
        m_messageId = msgInfo.messageId();
        m_chatSessionId = msgInfo.chatSessionId();
        m_time = formatTime(msgInfo.timestamp()); // 约定以“秒”为单位
        m_sender.load(msgInfo.sender());

        auto type = msgInfo.message().messageType();
        if(type == im::MessageTypeGadget::MessageType::STRING){
            m_type = TEXT_TYPE;
            m_content = msgInfo.message().stringMessage().content().toUtf8();
        }else if(type == im::MessageTypeGadget::MessageType::IMAGE){
            m_type = IMAGE_TYPE;
            if(msgInfo.message().imageMessage().hasFileId()){
                m_fileId = msgInfo.message().imageMessage().fileId();
            }
            if(msgInfo.message().imageMessage().hasImageContent()){
                m_content = msgInfo.message().imageMessage().imageContent();
            }
        }else if(type == im::MessageTypeGadget::MessageType::FILE){
            m_type = FILE_TYPE;
            m_fileName = msgInfo.message().fileMessage().fileName();
            if(msgInfo.message().fileMessage().hasFileId()){
                m_fileId = msgInfo.message().fileMessage().fileId();
            }
            if(msgInfo.message().fileMessage().hasFileContents()){
                m_content = msgInfo.message().fileMessage().fileContents();
            }
        }else if(type == im::MessageTypeGadget::MessageType::SPEECH){
            m_type = SPEECH_TYPE;
            if(msgInfo.message().speechMessage().hasFileId()){
                m_fileId = msgInfo.message().speechMessage().fileId();
            }
            if(msgInfo.message().speechMessage().hasFileContents()){
                m_content = msgInfo.message().speechMessage().fileContents();
            }
        }else{
            m_type = UNKNOWN_TYPE;
            LOG() << "未知消息";
        }

    }

private:
    static QString makeId(){
        return "M" + QUuid::createUuid().toString().sliced(25,12);
    }

    static Message makeTextMessage(const UserInfo& sender,
                                   const QString& chatSessionId, const QByteArray& content){
        Message text;
        text.m_messageId = makeId();
        text.m_chatSessionId = chatSessionId;
        text.m_sender = sender;
        text.m_type = TEXT_TYPE;
        text.m_content = content;
        text.m_time = formatTime(getTime());
        return text;
    }

    static Message makeImageMessage(const UserInfo& sender,
                                    const QString& chatSessionId, const QByteArray& content){
        Message image;
        image.m_messageId = makeId();
        image.m_chatSessionId = chatSessionId;
        image.m_sender = sender;
        image.m_type = IMAGE_TYPE;
        image.m_content = content;
        image.m_time = formatTime(getTime());
        return image;
    }

    static Message makeSpeechMessage(const UserInfo& sender,
                                     const QString& chatSessionId, const QByteArray& content){
        Message speech;
        speech.m_messageId = makeId();
        speech.m_chatSessionId = chatSessionId;
        speech.m_sender = sender;
        speech.m_type = SPEECH_TYPE;
        speech.m_content = content;
        speech.m_time = formatTime(getTime());
        return speech;
    }

    static Message makeFileMessage(const UserInfo& sender, const QString& chatSessionId,
                                   const QByteArray& content, const QString& extraInfo){
        Message file;
        file.m_messageId = makeId();
        file.m_chatSessionId = chatSessionId;
        file.m_sender = sender;
        file.m_type = FILE_TYPE;
        file.m_content = content;
        file.m_time = formatTime(getTime());
        // TODO:
        file.m_fileId = "";
        file.m_fileName = "";
        return file;
    }
};


///////////////////////////
/// 群聊会话
///////////////////////////
class chatSessionInfo{
public:
    QString m_chatSessionId = "";   // 群ID
    QString m_chatSessionName = ""; // 群名称
    Message m_message;              // 最近消息内容
    QIcon m_avatar;                 // 群头像
    QString m_userId = "";          // 分为两人对话，和2人以上的对话，两人就是对方的ID，群聊就为空

    void load(const im::ChatSessionInfo& chatSessionInfo){
        m_chatSessionId = chatSessionInfo.chatSessionId();
        m_chatSessionName = chatSessionInfo.chatSessionName();

        if(chatSessionInfo.hasPrevMessage()){
            m_message.load(chatSessionInfo.prevMessage());
        }
        if (chatSessionInfo.hasAvatar() && !chatSessionInfo.avatar().isEmpty()) {
            // 响应中有会话头像
            m_avatar = makeIcon(chatSessionInfo.avatar());
        } else {
            // 单聊和群聊设置不同的默认头像
            if (m_userId != "") {
                // 单聊头像
                m_avatar = QIcon(":/resource/image/defaultAvatar.png");
            } else {
                // 群聊头像
                m_avatar = QIcon(":/resource/image/groupAvatar.png");
            }
        }
        if(chatSessionInfo.hasSingleChatFriendId()){
            m_userId = chatSessionInfo.singleChatFriendId();
        }
    }
};
}   // end mode
